home *** CD-ROM | disk | FTP | other *** search
/ The Learning Curve / The Learning Curve (Weird Science, 1996).iso / libs / backstab.s < prev    next >
Text File  |  1992-09-02  |  26KB  |  1,045 lines

  1. ;*******************************
  2. ;**** BACKSTAB.LIBRARY V1.0 ****
  3. ;****    By Sami Vaarala    ****
  4. ;*******************************
  5.  
  6. err_audio:    equ    -1        ;error message definitions (-1 .. -128)
  7. err_cache:    equ    -2
  8.  
  9.     ;Library call offsets:
  10.     ;
  11.     ;TakeOverSystem        -30        \
  12.     ;ReturnToSystem        -36         \ these 4 form the method I
  13.     ;ActivateSystem        -42         /
  14.     ;DeactivateSystem    -48        /
  15.     ;
  16.     ;FullTakeOver        -54        \ these 2 form the method II
  17.     ;DoReset        -60        /
  18.     ;
  19.     ;FlushCaches        -66
  20.     ;
  21.     ;If there is a need for any special routines, add them here. Especially
  22.     ;if Exec needs patching for a routine, the routine can be included here
  23.     ;in full.
  24.  
  25. start:
  26.  
  27. call:    macro
  28.     jsr    _LVO\1(a6)
  29.     endm
  30. go:    macro
  31.     jmp    _LVO\1(a6)
  32.     endm
  33.  
  34.     incdir    B:text/howtocode/source/include/    ;new includes from
  35.     include    graphics_lib.i                ;howtocode 7
  36.     include    intuition_lib.i
  37.  
  38.     incdir    p:oinc/
  39.     include    exec/exec_lib.i
  40.     include    exec/execbase.i
  41.     include    exec/exec.i
  42.     include    exec/types.i
  43.     include    exec/initializers.i
  44.     include    exec/libraries.i
  45.     include    exec/lists.i
  46.     include    exec/alerts.i
  47.     include    exec/resident.i
  48.     include    exec/ports.i
  49.     include    libraries/dos.i
  50.     ;include    graphics/graphics_lib.i
  51.     include    graphics/gfxbase.i
  52.     include    libraries/dos_lib.i
  53.     ;include    intuition/intuition_lib.i
  54.     include    intuition/intuitionbase.i
  55.     include    workbench/workbench.i
  56.  
  57.     ;All the includes from the "include:" are <KS2.0 (1.2/1.3) includes,
  58.     ;and so I've 'updated' some of the libraries from HowToCode7.
  59.     ;Ofcourse if you have better versions of the includes, use them!
  60.  
  61. ;**** sprite resolutions, taken from OS3.0 includes "include/graphics/view.i"
  62. SPRITERESN_ECS        equ    0
  63. SPRITERESN_140NS     equ    1
  64. SPRITERESN_70NS        equ    2
  65. SPRITERESN_35NS        equ    3
  66.  
  67. ;**** other include from "include/graphics/videocontrol.i"
  68. VTAG_SPRITERESN_SET    equ    $80000031
  69. VTAG_SPRITERESN_GET    equ    $80000032
  70.  
  71. ;**** from "include/utility/tagitem.i"
  72. TAG_DONE   equ 0  ; terminates array of TagItems. ti_Data unused
  73.  
  74. _LVOCacheClearU:    equ    -636    ;from new Exec includes
  75. _LVOCacheControl:    equ    -648    ;
  76.  
  77. GFXB_AA_ALICE:        equ    2    ;from HowToCode
  78. gb_ChipRevBits0:    equ    $ec    ;
  79.  
  80. VERSION:    equ    1        ;version number (0...255)
  81. REVISION:    equ    0        ;revision number (0...255)
  82.  
  83.     ;lib base
  84.     RSRESET
  85. bks_flags:    rs.b    1    ;lib flags
  86. bks_pad:    rs.b    1    ;alignment
  87. bks_syslib:    rs.l    1    ;execbase
  88. bks_seglist:    rs.l    1    ;seglist-pointer
  89. bks_size:    rs.w    0    ;size of structure
  90.  
  91. bks_sizeof:    equ    bks_size+LIB_SIZE ;=> real size of lib base
  92.  
  93.     moveq    #-1,d0            ;if someone runs us...
  94.     rts                ;
  95.  
  96.     ;Exec will seek for matchword and check if next longword pointer
  97.     ;matches matchword also...
  98.  
  99. ROMTag:    dc.w    RTC_MATCHWORD    ;uword    rt_matchword
  100.     dc.l    ROMTag        ;aptr    rt_matchtag
  101.  
  102.     dc.l    EndOfLib    ;aptr    rt_endskip    = end of library
  103.  
  104.     dc.b    RTF_AUTOINIT    ;ubyte    rt_flags    = auto initialized lib
  105.     dc.b    VERSION        ;ubyte    rt_version    > from EQU
  106.     dc.b    NT_LIBRARY    ;ubyte    rt_type        = use type LIBRARY
  107.     dc.b    0        ;ubyte    rt_pri        ???
  108.  
  109.     dc.l    LibName        ;aptr    rt_name
  110.     dc.l    LibID        ;aptr    rt_idstring
  111.     dc.l    InitStuff    ;aptr    rt_init        ???
  112.  
  113.  dc.b "$VER: backstab.library version 1.0 by Sami Vaarala in 6.12.93",0
  114.  even
  115.  
  116. InitStuff:
  117.     dc.l    bks_sizeof    ;structure size (library base???)
  118.     dc.l    Functions    ;function list
  119.     dc.l    LibBaseData    ;information for initializing (!?)
  120.     dc.l    InitRoutine    ;own routine for initialization
  121.  
  122. Functions:
  123.     dc.l    r_open        ;Open()        -    the basic lib functions
  124.     dc.l    r_close        ;Close()
  125.     dc.l    r_expunge    ;Expunge()
  126.     dc.l    r_null        ;reserved...
  127.  
  128.     dc.l    r_takeover    ;TakeOverSystem() - run your program after this
  129.     dc.l    r_return    ;ReturnToSystem() - exit with this
  130.     dc.l    r_activate    ;ActivateSystem() - temp. activ. for loading...
  131.     dc.l    r_deactivate    ;DeactivateSystem() - after ActivateSystem()
  132.  
  133.     dc.l    r_fulltakeover    ;FullTakeOver() - now able to _wreck_ CIAs!
  134.     dc.l    r_reset        ;DoReset() - reset the amiga
  135.  
  136.     dc.l    r_flushcaches    ;FlushCaches() - flush all caches (if higher
  137.                 ;than V37)
  138.  
  139.     dc.l    -1        ;ENDMARK!
  140.  
  141.  
  142. LibBaseData:    INITBYTE    LN_TYPE,NT_LIBRARY
  143.         INITLONG    LN_NAME,LibName
  144.         INITBYTE    LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
  145.         INITWORD    LIB_VERSION,VERSION
  146.         INITWORD    LIB_REVISION,REVISION
  147.         INITLONG    LIB_IDSTRING,LibID
  148.         dc.l    0    ;end!
  149.     
  150. InitRoutine:
  151.     move.l    a5,-(sp)        ;store a5
  152.     move.l    d0,a5            ;lib base address to a5
  153.  
  154.     move.l    a6,bks_syslib(a5)     ;execbase to device        ??!
  155.     move.l    a0,bks_seglist(a5)    ;seglist to device        ??!
  156.  
  157.      move.l    #$400,d0        ;alloc 0-page copy buffer
  158.      moveq    #0,d1            ;
  159.      call    AllocMem        ;
  160.      move.l    d0,zero_copy        ;
  161.      beq.s    .panic            ;
  162.  
  163.      ;Opens all required libs: DOS, Intuition and Graphics. If any of these
  164.      ;fails, the library won't open!
  165.      move.l    4.w,a6            ;
  166.      lea    dosn(pc),a1        ;
  167.      moveq    #0,d0            ;
  168.      call    OpenLibrary        ;
  169.       move.l    d0,dos_base        ;
  170.      beq.w    .nod            ;
  171.      lea    intn(pc),a1        ;
  172.      moveq    #0,d0            ;
  173.      call    OpenLibrary        ;
  174.       move.l    d0,int_base        ;
  175.      beq.w    .noi            ;
  176.      lea    gfxn(pc),a1        ;
  177.      moveq    #0,d0            ;
  178.      call    OpenLibrary        ;
  179.      move.l    d0,gfx_base        ;
  180.      beq.s    .nog            ;zero flag = 0 (D0 != 0)
  181.  
  182.     move.l    a5,d0            ;
  183.     ;lib base is in D0 (for return value)
  184.     move.l    (sp)+,a5        ;restore a5
  185.     rts                ;
  186.  
  187. .nog:     move.l    int_base(pc),a1        ;Close down the libs that were opened
  188.      call    CloseLibrary        ;
  189. .noi:     move.l    dos_base(pc),a1        ;
  190.      call    CloseLibrary        ;
  191. .nod:
  192. .panic:
  193.      moveq    #-1,d0            ;As we can't necessarily display an
  194. .cols:     move.w    #$f00,$dff180        ;alert, let's use colors instead!
  195.      move.w    #$ff0,$dff180        ;
  196.      dbf    d0,.cols        ;
  197.      moveq    #0,d0            ;zero flag = 1 (D0 = 0)
  198.      rts                ;
  199.  
  200.  
  201. r_open:
  202.     addq.w    #1,LIB_OPENCNT(a6)    ;new user, nest him. expunge is thereby
  203.     bclr    #LIBB_DELEXP,bks_flags(a6);forbidden!
  204.     move.l    a6,d0            ;return base address in D0!
  205.     rts                ;
  206.  
  207.  
  208. r_close:
  209.     subq.w    #1,LIB_OPENCNT(a6)    ;one user less, if not last one, exit!
  210.     bne.s    r_close_notlast          ;
  211.  
  212.     btst    #LIBB_DELEXP,bks_flags(a6);delayed expunge? no, exit!
  213.     beq.s    r_close_nodelayedexpunge   ;
  214.  
  215.     bsr.s    r_expunge        ;use Expunge() as a subroutine!
  216. r_close_nodelayedexpunge:
  217. r_close_notlast:
  218.     moveq    #0,d0            ;return zero
  219.     rts                ;
  220.  
  221.  
  222. r_expunge:
  223.     move.l    a5,-(sp)        ;store...
  224.     move.l    a6,a5            ;lib base
  225.     move.l    bks_syslib(a5),a6    ;exec base
  226.  
  227.     tst.w    LIB_OPENCNT(a5)        ;library still open? yes, use delayed
  228.     beq.s    r_expunge_ok        ;expunge! else go for it!
  229.  
  230.     bset    #LIBB_DELEXP,bks_flags(a5);
  231.     move.l    a5,a6            ;
  232.     move.l    (sp)+,a5        ;restore...
  233.     moveq    #0,d0            ;return zero    
  234.     rts                ;
  235.  
  236. r_expunge_ok:
  237.      move.l    zero_copy(pc),a1    ;Free 0-page buffer
  238.      move.l    #$400,d0        ;
  239.      call    FreeMem            ;
  240.  
  241.      ;Closes all opened libraries and all the other OS stuff that has been
  242.      ;affected.
  243.  
  244.      move.l    dos_base(pc),a1        ;Close all opened libraries
  245.      call    CloseLibrary        ;
  246.      move.l    int_base(pc),a1        ;
  247.      call    CloseLibrary        ;
  248.      move.l    gfx_base(pc),a1        ;
  249.      call    CloseLibrary        ;
  250.  
  251.     move.l    d2,-(sp)        ;
  252.  
  253.     move.l    bks_seglist(a5),d2    ;SegList-pointer for returning...
  254.  
  255.     move.l    a5,a1            ;lib base
  256.     call    Remove            ;kill library from exec lists...
  257.  
  258.     moveq    #0,d0            ;free library: get base address to a1
  259.     move.l    a5,a1            ;and size to D0.
  260.     move.w    LIB_NEGSIZE(a5),d0    ;
  261.     sub.l    d0,a1            ;
  262.     add.w    LIB_POSSIZE(a5),d0    ;
  263.     call    FreeMem            ;
  264.     move.l    d2,d0            ;return SegList pointer!
  265.  
  266.     move.l    (sp)+,d2        ;exit
  267.     move.l    a5,a6            ;
  268.     move.l    (sp)+,a5        ;
  269.     rts                ;
  270.  
  271. r_null:
  272.     moveq    #0,d0            ;no problem, illegal call!?
  273.     rts                ;
  274.  
  275.  
  276.  
  277. no_audio:
  278.     moveq    #err_audio,d0        ;error code and return
  279.     move.l    (sp)+,a6        ;
  280.     rts                ;
  281.  
  282.     ;*** actual routines starting from -30 ...
  283. r_takeover:
  284.     move.l    d0,flags        ;Store flags
  285.     move.l    a6,-(sp)        ;
  286.  
  287.     move.l    4.w,a6            ;New client! Task pointer to 'aud_task'
  288.     sub.l    a1,a1            ;(*in* the audio device structure)
  289.     call    FindTask        ;
  290.     move.l    d0,aud_task        ;
  291.     move.l    d0,a1            ;Set task priority as high as possible
  292.     moveq    #127,d0            ;to prevent someone running with us
  293.     call    SetTaskPri        ;
  294.     move.l    d0,old_taskpri        ;
  295.  
  296.     ;allocate audio channels and do an illegal audio reset
  297.     bsr.w    alloc_audio        ;Allocate audio (or takeover illegally)
  298.     beq.s    no_audio        ;If fails, exit with error code
  299.  
  300.     lea    $dff096,a0        ;Force audio DMAs and volumes off, for
  301.     moveq    #0,d0            ;extra safety.
  302.     move.w    d0,$0a8-$096(a0)    ;
  303.     move.w    d0,$0b8-$096(a0)    ;
  304.     move.w    d0,$0c8-$096(a0)    ;
  305.     move.w    d0,$0d8-$096(a0)    ;
  306.     move.w    #$000f,(a0)        ;
  307.  
  308.     move.l    4.w,a6            ;Disable interrupts
  309.     call    Disable            ;
  310.  
  311.     ;prepare internal variables
  312.     clr.l    old_VBR            ;VBR swap value
  313.     clr.l    chip_stores        ;Values that will be loaded when exited
  314.     clr.l    chip_stores+4        ;-> chipregs
  315.  
  316.  
  317.     ;check if caches can be disabled (in case it is required)
  318.     btst    #AFB_68020,AttnFlags+1(a6);If user is running <68020 (no caches
  319.     bne.s    .check_nocache        ;CPU), force NoCache flag down.
  320.     bclr    #0,flags+3        ;
  321. .check_nocache:
  322.     btst    #0,flags+3        ;Check if we can disable caches in case
  323.     beq.s    .nocache_ok        ;'nocache' flag is set.
  324.     move.w    LIB_VERSION(a6),d0    ;
  325.     cmp.w    #37,d0            ;
  326.     bhs.s    .nocache_ok        ;
  327.  
  328.     move.l    int_base(pc),a6        ;Alert user about the fault.
  329.     moveq    #0,d0            ;
  330.     lea    cache_alert(pc),a0    ;
  331.     moveq    #60,d1            ;
  332.     call    DisplayAlert        ;
  333.     tst.l    d0            ;D0 is nonzero if left was pressed
  334.     bne.s    .nocache_ok        ;(left means that we continue!)
  335.  
  336.     moveq    #err_cache,d0        ;Error code and exit
  337.     rts                ;
  338. .nocache_ok:
  339.  
  340.     ;reset graphic chips
  341.     bsr.w    reset_gfx        ;Reset graphics chips to OCS state
  342.  
  343.     move.l    4.w,a6            ;Fill zeropage with the current real
  344.     call    SuperState        ;zeropage (determined by VBR if >68010)
  345.     move.l    d0,oldsysstack        ;
  346.     moveq    #0,d0            ;
  347.     btst    #AFB_68010,AttnFlags+1(a6);
  348.     beq.s    .vbr_68000        ;
  349.     movec    vbr,d0            ;
  350. .vbr_68000                ;
  351.     move.l    d0,-(sp)        ;
  352.     move.l    oldsysstack(pc),d0    ;
  353.     call    UserState        ;
  354.                     ;
  355.     move.l    (sp)+,a1        ;
  356.     move.l    zero_copy(pc),a0    ;
  357.     move.w    #[$400/4]-1,d0        ;
  358. .fill:                    ;
  359.     move.l    (a1)+,(a0)+        ;
  360.     dbf    d0,.fill        ;
  361.  
  362.     ;'Deactivate' and 'takeover' have a common part from hereon, use that
  363.     ;for size optimization!
  364.  
  365.     bra.s    common_part_takeover    ;
  366.  
  367. r_deactivate:
  368.     ;Flags are the same as TakeOver() [still stored]
  369.  
  370.     move.l    a6,-(sp)        ;
  371.  
  372.     move.l    4.w,a6            ;Disable interrupts
  373.     call    Disable            ;
  374.  
  375. common_part_takeover:
  376.     bsr.w    wait_devices        ;Wait devices to finish
  377.     bsr.w    own_blitter        ;Takeover blitter
  378.  
  379.     bsr.w    reset_caches        ;Turn off caches if required
  380.  
  381.     move.l    4.w,a6            ;Go to supervisor mode (zeropage
  382.     call    SuperState        ;handling requires this)
  383.     move.l    d0,oldsysstack        ;
  384.  
  385.     bsr.w    swap_zeropage_and_vbr    ;Zeropage and VBR handling
  386.  
  387.     btst    #1,flags+3        ;If flag SUPERVISOR is set, don't go
  388.     bne.s    .nouser            ;back to userstate
  389.     move.l    4.w,a6            ;
  390.     move.l    oldsysstack(pc),d0    ;
  391.     call    UserState        ;
  392. .nouser:
  393.  
  394.     bsr.w    swap_chipregs        ;Chip handling
  395.  
  396.     bsr.w    get_return_datas    ;Get return datas abouut the system
  397.     move.l    (sp)+,a6        ;
  398.     moveq    #0,d0            ;error code = none
  399.     rts                ;
  400. .panic:
  401.     move.l    (sp)+,a6        ;
  402.     moveq    #err_cache,d0        ;
  403.     rts                ;
  404.  
  405. r_activate:
  406.     move.l    d2,-(sp)        ;
  407.     moveq    #0,d2            ;
  408.     bra.s    common_activation    ;
  409. r_return:
  410.     move.l    d2,-(sp)        ;
  411.     moveq    #-1,d2            ;
  412.     ;Just go on...
  413.  
  414. common_activation:
  415.     ;This piece of code is almost similar to 'ActivateSystem' and 'Return-
  416.     ;ToSystem'. The only difference is that ReturnToSystem frees audio
  417.     ;channels and restores gfx. To optimize size, D2 indicates which case
  418.     ;are we running, and some things are bypassed if it isn't ReturnTo-
  419.     ;System..
  420.  
  421.     move.l    a6,-(sp)        ;
  422.     move.w    #$4000,$dff09a        ;Disable interrupts
  423.  
  424.     bsr.w    swap_chipregs        ;Chip handling
  425.  
  426.     btst    #1,flags+3        ;If SUPERVISOR flag wasn't set, we have
  427.     bne.s    .was_super        ;to go into supervisor.
  428.     move.l    4.w,a6            ;
  429.     call    SuperState        ;
  430.     move.l    d0,oldsysstack        ;
  431. .was_super:
  432.     bsr.w    swap_zeropage_and_vbr    ;Swap zeropage and VBR
  433.  
  434.     move.l    4.w,a6            ;Back to userstate
  435.     move.l    oldsysstack(pc),d0    ;
  436.     call    Userstate        ;
  437.  
  438.     bsr.w    restore_caches        ;Restore cache states
  439.  
  440.     bsr.w    disown_blitter        ;Blitter back to system
  441.  
  442.     tst.w    d2            ;System view back (if ReturnToSystem)
  443.     beq.s    .only_in_return1    ;
  444.     bsr.w    restore_gfx        ;
  445. .only_in_return1:
  446.  
  447.     move.l    4.w,a6            ;Enable interrupts
  448.     call    Enable            ;
  449.  
  450.     tst.w    d2            ;Audio chans back (if ReturnToSystem)
  451.     beq.s    .only_in_return2    ;
  452.  
  453.     lea    $dff096,a0        ;Illegal audio reset before giving back
  454.     moveq    #0,d0            ;audio channels to system.
  455.     move.w    d0,$0a8-$096(a0)    ;
  456.     move.w    d0,$0b8-$096(a0)    ;
  457.     move.w    d0,$0c8-$096(a0)    ;
  458.     move.w    d0,$0d8-$096(a0)    ;
  459.     move.w    #$000f,(a0)        ;
  460.                     ;
  461.     bsr.w    restore_audio        ;Audio channels back
  462.                     ;
  463.     move.l    4.w,a6            ;Task priority back
  464.     move.l    aud_task(pc),a1        ;
  465.     move.l    old_taskpri(pc),d0    ;
  466.     call    SetTaskPri        ;
  467.  
  468. .only_in_return2:
  469.  
  470.     move.l    (sp)+,a6        ;
  471.     move.l    (sp)+,d2        ;
  472.     rts                ;
  473.  
  474.  
  475.     ;This routine is exactly same as TakeOverSystem() at the moment, but
  476.     ;in future versions this routine can kill system less legally if
  477.     ;needed. This routine is here just for compatibility and expandability
  478.     ;of future versions.
  479.  
  480. r_fulltakeover:
  481.     bra.w    r_takeover        ;Use same routine
  482.  
  483. r_reset:
  484.     ;The Exec code under V39 (A1200) does NOT work properly. Proper reset
  485.     ;routines ARE possible, I don't have an idea how. If someone knows of
  486.     ;a _proper_ (preferable Commodore recommended) way to do this, REPORT!
  487.     ;
  488.     ;This is written as the Commodores ''supported'' reset routine is.
  489.  
  490. ROMEND:        equ    $01000000    ;
  491. SIZE_OFFSET:    equ    -$14        ;
  492.  
  493. KICK_V36:    equ    36        ;
  494. V36_ColdReboot:    equ    -726        ;
  495.  
  496.     move.l    4.w,a6            ;
  497.     cmp.w    #KICK_V36,LIB_VERSION(a6);
  498.     blt.s    .old_kick        ;
  499.  
  500.     jmp    V36_ColdReboot(a6)    ;Use V36 or upwards reset code
  501.  
  502. .old_kick:
  503.     move.w    #$4000,$dff09a        ;(I feel safer this way, so does KS3.0)
  504.  
  505.     ;KS3.0 disables caches here as well, no reason to do it if <V36?
  506.  
  507.     lea    .Reset_Code(pc),a5    ;
  508.     jsr    _LVOSupervisor(a6)    ;
  509.     ;never here, supervisor jumps to reset code
  510.  
  511.     cnop    0,4            ;DON'T TOUCH!
  512. .Reset_Code:
  513.     lea    ROMEND,a0        ;Calc entrypoint
  514.     sub.l    SIZE_OFFSET(a0),a0    ;
  515.     move.l    4(a0),a0        ;
  516.     subq.l    #2,a0            ;
  517.     reset                ;reset peripherie
  518.     jmp    (a0)            ;done
  519.  
  520.     ;! <reset> and <jmp (a0)> in the same longword! (i.e. reset address
  521.     ;bits 0 and 1 are zero)
  522.  
  523.  
  524. r_flushcaches:
  525.     move.l    a6,-(sp)        ;
  526.     move.l    4.w,a6            ;KS2.04 or higher? No, alert user!
  527.     move.w    LIB_VERSION(a6),d0    ;
  528.     cmp.w    #37,d0            ;
  529.     blo.s    .noflush        ;
  530.  
  531.     call    CacheClearU        ;Flush it!
  532.     move.l    (sp)+,a6        ;
  533.     moveq    #0,d0            ;
  534.     rts                ;No error: D0 = 0
  535. .noflush:
  536.     move.l    (sp)+,a6        ;
  537.     moveq    #-1,d0            ;ERROR! D0 = -1
  538.     rts                ;
  539.  
  540.  
  541.  
  542.     ;*** Subroutines
  543.  
  544. get_return_datas:
  545.     moveq    #0,d1            ;Start from OCS
  546.  
  547.     move.l    4.w,a6            ;>PROB< I don't know if one is able to
  548.     cmp.w    #36,LIB_VERSION(a6)    ;check chipset under 1.2/1.3, so this
  549.     blo.s    .nocheck        ;is for 'safety'?
  550.  
  551.     move.l    gfx_base(pc),a6        ;
  552.     btst    #GFXB_AA_ALICE,gb_ChipRevBits0(a6)
  553.     bne.s    .aga            ;
  554.     btst    #1,gb_ChipRevBits0(a6)    ;
  555.     beq.s    .checkover        ;
  556.     moveq    #1,d1            ;
  557.     bra.s    .checkover        ;
  558. .aga:    moveq    #2,d1            ;
  559. .nocheck:
  560. .checkover:
  561.  
  562.     move.l    4.w,a6            ;Get Kickstart version (= Exec version)
  563.     moveq    #0,d2            ;
  564.     move.w    LIB_VERSION(a6),d2    ;
  565.  
  566.     move.w    AttnFlags(a6),d0    ;Get CPU number
  567.     btst    #3,d0            ;
  568.     bne.s    .040            ;
  569.     btst    #2,d0            ;
  570.     bne.s    .030            ;
  571.     btst    #1,d0            ;
  572.     bne.s    .020            ;
  573.     btst    #0,d0            ;
  574.     bne.s    .010            ;
  575.     moveq    #0,d3            ;
  576.     bra.s    .CPUover        ;
  577. .010:    moveq    #1,d3            ;
  578.     bra.s    .CPUover        ;
  579. .020:    moveq    #2,d3            ;
  580.     bra.s    .CPUover        ;
  581. .030:    moveq    #3,d3            ;
  582.     bra.s    .CPUover        ;
  583. .040:    moveq    #4,d3            ;
  584. .CPUover:
  585.     moveq    #0,d4            ;Get math emulation types
  586.     lsr.w    #4,d0            ;
  587.     and.w    #%111,d0        ;
  588.     move.w    d0,d4            ;
  589.  
  590.     rts                ;
  591.  
  592. reset_caches:
  593.     clr.l    old_cachebits        ;(rerunning has to be possible)
  594.  
  595.     btst    #0,flags+3        ;NoCache? Yes, exit
  596.     beq.s    .noreq            ;
  597.  
  598.     ;If we are here, the CPU -has- caches and they are killable.
  599.  
  600.     move.l    4.w,a6            ;
  601.     call    CacheClearU        ;Safety flush (surely Exec does this?)
  602.  
  603.     moveq    #0,d0            ;Get old cache state
  604.     moveq    #0,d1            ;
  605.     call    CacheControl        ;
  606.     move.l    d0,old_cachebits    ;
  607.  
  608.     move.l    d0,d1            ;Clear only SET bits to avoid masking
  609.     moveq    #0,d0            ;d1 with -1
  610.     call    CacheControl        ;
  611. .noreq:
  612.     rts                ;
  613.  
  614.  
  615. restore_caches:
  616.     move.l    old_cachebits(pc),d0    ;
  617.     beq.s    .nofix            ;
  618.  
  619.     ;If the cache was fixed, it's possible to unfix it! [no error checks]
  620.  
  621.     move.l    4.w,a6            ;Reset old cache state: set all bits
  622.     move.l    old_cachebits(pc),d0    ;with identical mask!
  623.     move.l    d0,d1            ;
  624.     call    CacheControl        ;
  625. .nofix:
  626.     rts                ;
  627.  
  628.  
  629. alloc_audio:
  630.     ;Allocates and initializes audio channels and returns zero flag set if
  631.     ;the audio wasn't ok: exit the whole shit. Also illegally turns the
  632.     ;audio DMA off along with volumes that are set to zero. Ofcourse only
  633.     ;if channels were allocated or user agreed to takeover.
  634.  
  635.     ;Initialize structure for OpenDevice(), which will allocate the
  636.     ;channels specifies in the channel map structure. The mask is always
  637.     ;(in this code) %1111, and that is the only entry. -> All channels are
  638.     ;always allocated.
  639.  
  640.     clr.b    audio_alloc        ;Reset audio allocated flag
  641.  
  642.     ;Task pointer is already set into the structure!
  643.  
  644.     moveq    #-1,d0            ;AllocSignal for audio device
  645.     call    AllocSignal        ;
  646.     move.b    d0,aud_signal        ;
  647.     bmi.s    .nosig            ;
  648.  
  649.     lea    aud_messageport(pc),a1    ;Add msgport into system lists
  650.     call    AddPort            ;
  651.     tst.l    d0            ;
  652.     beq.s    .noport            ;
  653.  
  654.     ;Open the device. Strangely, no IO command needs to be assigned for
  655.     ;allocation (by the books). Priority 127 means that no-one can steal
  656.     ;these channels no more, in effect no handling for stolen channels is
  657.     ;required.
  658.  
  659.     lea    audn(pc),a0        ;name ("audio.device")
  660.     moveq    #0,d0            ;unit (always 0)
  661.     lea    aud_ioreq(pc),a1    ;ioreq
  662.     moveq    #0,d1            ;flags (always 0)
  663.     call    OpenDevice        ;
  664.     tst.l    d0            ;
  665.     bne.s    .nodev            ;
  666.  
  667.     not.b    audio_alloc        ;flag: audio allocated!
  668.     rts                ;zeroflag = 0
  669.  
  670. .nodev:
  671.     lea    aud_messageport(pc),a1    ;Handle errors, display alert for user
  672.     call    RemPort            ;to choose whether to exit demo or
  673. .noport:                ;take over anyway
  674.     moveq    #0,d0            ;
  675.     move.b    aud_signal(pc),d0    ;
  676.     call    FreeSignal        ;
  677. .nosig:                    ;
  678.     move.l    int_base(pc),a6        ;
  679.     moveq    #0,d0            ;
  680.     lea    audio_alert(pc),a0    ;
  681.     moveq    #60,d1            ;
  682.     call    DisplayAlert        ;
  683.  
  684.     tst.l    d0            ;If RMB pressed -> cancel -> D0=zero ->
  685.     rts                ;zeroflag set. Else zeroflag=0.
  686.  
  687.  
  688. restore_audio:
  689.     tst.b    audio_alloc        ;If audio was allocated, get
  690.     beq.s    .audio_over        ;rid of it and all the system
  691.                     ;stuff needed for it.
  692.     move.l    4.w,a6            ;
  693.     lea    aud_ioreq(pc),a1    ;
  694.     call    CloseDevice        ;
  695.     lea    aud_messageport(pc),a1    ;
  696.     call    RemPort            ;
  697.     moveq    #0,d0            ;
  698.     move.b    aud_signal(pc),d0    ;
  699.     call    FreeSignal        ;
  700. .audio_over:
  701.     rts                ;
  702.  
  703.  
  704. wait_devices:
  705.     ;Somekind of device wait would be ideal here. Anyone know how to wait
  706.     ;for all devices to finish?
  707.     rts                ;
  708.  
  709.  
  710.  
  711.  
  712. reset_gfx:
  713.     ;Flushes all graphics hardware to basic state (according to system).
  714.  
  715.     ;If V39 or higher, forces sprites back to 140ns resolution. No return
  716.     ;codes.
  717.  
  718.     sub.l    a1,a1            ;
  719.     call    FindTask        ;
  720.     move.l    d0,a1            ;
  721.  
  722.     clr.l    wbscreen        ;If someone runs us again...
  723.  
  724.     move.l    4.w,a6            ;The sprite fix only if KS 3.0 (V39)
  725.     move.w    LIB_VERSION(a6),d0    ;or higher.
  726.     cmp.w    #39,d0            ;
  727.     blo.w    .exit            ;
  728.  
  729.     move.l    #VTAG_SPRITERESN_GET,taglist;must work even if many calls...
  730.     move.l    #SPRITERESN_ECS,res    ;
  731.  
  732.     move.l    int_base(pc),a6        ;Store old resolution
  733.     lea    wbn(pc),a0        ;
  734.     call    LockPubScreen        ;
  735.     move.l    d0,wbscreen        ;
  736.     beq.s    .exit            ;
  737.     move.l    d0,a0            ;
  738.                     ;
  739.     move.l    sc_ViewPort+vp_ColorMap(a0),a0;
  740.     lea    taglist(pc),a1        ;
  741.     move.l    gfx_base(pc),a6        ;
  742.     call    VideoControl        ;
  743.     move.l    res,oldres        ;
  744.  
  745.         move.l    #VTAG_SPRITERESN_SET,taglist;Reset sprites to 140ns resolution
  746.         move.l    #SPRITERESN_140NS,res    ;
  747.                     ;
  748.         move.l    wbscreen(pc),a0        ;
  749.         move.l    sc_ViewPort+vp_ColorMap(a0),a0;
  750.         lea    taglist(pc),a1        ;
  751.     call    VideoControl        ;
  752.  
  753.     move.l    wbscreen(pc),a0        ;Make system actually do the change
  754.     move.l    int_base(pc),a6        ;reality
  755.     call    MakeScreen        ;
  756.     call    RethinkDisplay        ;
  757.  
  758.     move.l    gfx_base(pc),a6        ;Wait for the change...
  759.     call    WaitTOF            ;
  760.     call    WaitTOF            ;
  761.     ;Sprites are now 140ns!
  762. .exit:
  763.     move.l    gfx_base(pc),a6        ;Store system view and reset the
  764.     move.l  gb_ActiView(a6),sysview    ;graphics hardware to the original
  765.     sub.l    a1,a1            ;state: AGA is flushed. The bug in the
  766.     call    LoadView        ;LoadView(NULL) leaves AGA sprites un-
  767.     call    WaitTOF            ;fixed, but that was handled before.
  768.     go    WaitTOF            ;(wait twice for interlace)
  769.  
  770. restore_gfx:
  771.     move.l    wbscreen(pc),d0        ;Reset sprites to original rez,
  772.     beq.s    .exit            ;if WBscreen not available do
  773.     move.l    d0,a0            ;nothing
  774.  
  775.     ;If < V39, the wbscreen will be zero, so exit is ok!
  776.     ;
  777.     ;VTAG command has to be set to 'SET' now, as we exited TakeOver with
  778.     ;that value...
  779.     move.l    oldres(pc),res        ;
  780.     lea    taglist(pc),a1        ;
  781.     move.l    sc_ViewPort+vp_ColorMap(a0),a0    ;
  782.     move.l    gfx_base(pc),a6        ;
  783.     call    VideoControl        ;
  784.  
  785.     move.l    int_base(pc),a6        ;Make system believe the truth.
  786.     move.l    wbscreen(pc),a0        ;
  787.     call    MakeScreen        ;(ReThinkDisplay() done later on)
  788.  
  789.     move.l    wbscreen(pc),a1        ;
  790.     sub.l    a0,a0            ;(Unlock the WB screen)
  791.     call    UnlockPubScreen        ;
  792.  
  793.     move.l    gfx_base(pc),a6        ;Wait for the change...
  794.     ;Sprites are now in original resolution
  795. .exit:
  796.     move.l    gfx_base(pc),a6        ;Restore original view
  797.     move.l    sysview(pc),a1        ;
  798.     call    LoadView        ;
  799.     call    WaitTOF            ;(if interlace)
  800.     call    WaitTOF            ;
  801.  
  802.     move.l    gb_copinit(a6),$dff080    ;Reset copper 1 address
  803.  
  804.     move.l    int_base(pc),a6        ;Rethink...
  805.     go    ReThinkDisplay        ;
  806.  
  807.  
  808.  
  809. own_blitter:
  810.     ;Take over blitter and wait for it to get done totally.
  811.  
  812.     move.l    gfx_base(pc),a6        ;
  813.     call    OwnBlitter        ;*some* blit safety! Wait blitter twice
  814.     call    WaitBlit        ;with system routines and then with an
  815.     call    WaitBlit        ;own illegal waitup. No config should
  816.     btst    #14,$dff002        ;go through that one unnoticed? :)
  817. .wblit:                    ;
  818.     btst    #14,$dff002        ;
  819.     bne.s    .wblit            ;
  820.     rts                ;
  821.  
  822. disown_blitter:
  823.     btst    #14,$dff002            ;Wait and disown blitter
  824. .wblit:                        ;(some safety here also...)
  825.     btst    #14,$dff002            ;
  826.     bne.s    .wblit                ;
  827.     move.l    gfx_base(pc),a6            ;
  828.     call    WaitBlit            ;
  829.     call    WaitBlit            ;
  830.     call    DisownBlitter            ;
  831.     rts                    ;
  832.  
  833. swap_zeropage_and_vbr:
  834.     ;Requires SUPERVISOR mode!
  835.  
  836.     move.l    zero_copy(pc),a0        ;Swap stored zeropage with the
  837.     sub.l    a1,a1                ;real zeropage (physical,
  838.     move.w    #$400/4-1,d0            ;starting from $0)
  839. .swap:                        ;
  840.     move.l    (a0),d1                ;
  841.     move.l    (a1),(a0)+            ;
  842.     move.l    d1,(a1)+            ;
  843.     dbf    d0,.swap            ;
  844.  
  845.     move.l    4.w,a6                ;If >68010, swap stored and
  846.     btst    #AFB_68010,AttnFlags+1(a6)    ;real VBR (the runned program's
  847.     beq.s    .vbr_68000            ;VBR is always zero, though)
  848.     move.l    old_vbr(pc),d0            ;
  849.     movec    vbr,d1                ;
  850.     move.l    d1,old_vbr            ;
  851.     movec    d0,vbr                ;
  852. .vbr_68000:                    ;
  853.     rts                    ;
  854.  
  855.  
  856.  
  857.  
  858. swap_chipregs:
  859.     ;Wait for disk DMA to finish and swap the 4 important chipregs
  860.  
  861.     lea    $dff096,a0            ;Custom base
  862.  
  863.     btst    #14,$01a-$096(a0)        ;Wait disk DMA for maximum
  864.     beq.s    .nodiskdma            ;certainty!
  865. .diskdma:                    ;
  866.     btst    #1,$01e+1-$096(a0)        ;DO NOT clear the bit, system
  867.     beq.s    .diskdma            ;may be expecting it...
  868. .nodiskdma:
  869.  
  870.     move.w    $002-$096(a0),d1        ;
  871.     move.w    old_dmacon(pc),d0        ;
  872.     bset    #15,d0                ;
  873.     and.w    #%1000011111111111,d0        ;
  874.     move.w    d0,(a0)                ;
  875.     not.w    d0                ;
  876.     and.w    #%1000011111111111,d0        ;
  877.     move.w    d0,(a0)                ;
  878.     move.w    d1,old_dmacon            ;
  879.                         ;
  880.     move.w    $01c-$096(a0),d1        ;
  881.     move.w    old_intena(pc),d0        ;(master is disabled!)
  882.     bset    #15,d0                ;
  883.     move.w    d0,$09a-$096(a0)        ;
  884.     not.w    d0                ;
  885.     move.w    d0,$09a-$096(a0)        ;
  886.     move.w    d1,old_intena            ;
  887.                         ;
  888.     move.w    $01e-$096(a0),d1        ;
  889.     move.w    old_intreq(pc),d0        ;
  890.     bset    #15,d0                ;
  891.     move.w    d0,$09c-$096(a0)        ;
  892.     not.w    d0                ;
  893.     move.w    d0,$09c-$096(a0)        ;
  894.     move.w    d1,old_intreq            ;
  895.                         ;
  896.     move.w    $010-$096(a0),d1        ;
  897.     move.w    old_adkcon(pc),d0        ;
  898.     bset    #15,d0                ;
  899.     move.w    d0,$09e-$096(a0)        ;
  900.     not.w    d0                ;
  901.     move.w    d0,$09e-$096(a0)        ;
  902.     move.w    d1,old_adkcon            ;
  903.     rts                    ;
  904.  
  905.  
  906. aud_ioreq:    dc.l    0        ;succ        \
  907.         dc.l    0        ;pred         \
  908.         dc.b    5        ;type = message       node structure
  909.         dc.b    127        ;pri         / (in message struct)
  910.         dc.l    0        ;name        /
  911.  
  912. aud_msgport:    dc.l    aud_messageport    ;message port          \ actual message
  913.         dc.w    0        ;byte nbr of message  / structure
  914.  
  915.         dc.l    0        ;device
  916.         dc.l    0        ;unit
  917.  
  918. aud_cmd:    dc.w    0        ;command
  919. aud_flags:    dc.b    0        ;flags
  920. aud_error:    dc.b    0        ;error
  921.  
  922.         ;here begins the audio request extra datas
  923.  
  924. aud_allockey:    dc.w    0        ;allocation key (dev fills up)
  925. aud_data:    dc.l    channel_map    ;data pointer
  926. aud_len:    dc.l    1        ;size data field
  927. aud_per:    dc.w    0        ;frequency
  928. aud_vol:    dc.w    0        ;volume
  929. ayd_cycles:    dc.w    0        ;cycles
  930.  
  931.         ;this is the WriteMsg structure trailing the real IO req.
  932.         ;device will fill this space up, so only 14 zeros is ok.
  933.         ;
  934.         ;
  935.         blk.b    mn_size,0    ;device will fill this up (14 bytes)
  936.  
  937.  
  938. aud_messageport:dc.l    0        ;succ
  939.         dc.l    0        ;pred
  940.         dc.b    4        ;type = messageport
  941.         dc.b    0        ;pri
  942.         dc.l    0        ;name
  943.  
  944.         dc.b    0        ;flags
  945. aud_signal:    dc.b    0        ;signal bit
  946. aud_task:    dc.l    0        ;task
  947.  
  948.         dc.l    0        ;head
  949.         dc.l    0        ;tail
  950.         dc.l    0        ;tailpred
  951.         dc.b    0        ;type
  952.         dc.b    0        ;pad
  953.  
  954. oldres:        dc.l    0        ;Old sprite resolution
  955. wbscreen:    dc.l    0        ;WB screen
  956.  
  957. taglist:    dc.l      0        ;VTAG command (set resn/get resn)
  958. res:        dc.l      0        ;resolution
  959. tagdone:    dc.l    TAG_DONE,0    ;
  960.  
  961.  
  962. flags:        dc.l    0        ;Takeover input flags
  963.  
  964. dos_base:    dc.l    0        ;dos base
  965. gfx_base:    dc.l    0        ;graphics base
  966. int_base:    dc.l    0        ;intuition base
  967. zero_copy:    dc.l    0        ;zeropage copy address
  968. old_VBR:    dc.l    0        ;old VBR
  969. old_taskpri:    dc.l    0        ;old task priority
  970. sysview:    dc.l    0        ;system view address
  971. oldsysstack:    dc.l    0        ;old stack pointer:superstate/userstate
  972. old_cachebits:    dc.l    0        ;old cache control bits
  973.  
  974. chip_stores:
  975. old_dmacon:    dc.w    0        ;chipreg storages...
  976. old_intena:    dc.w    0        ;
  977. old_intreq:    dc.w    0        ;
  978. old_adkcon:    dc.w    0        ;
  979.  
  980. audio_alloc:    dc.b    0        ;Flag: audio was allocated succesfully
  981.  
  982. channel_map:    dc.b    %1111        ;all 4 channels or nothing (alloc map)
  983.  
  984. dosn:    dc.b    'dos.library',0
  985. gfxn:    dc.b    'graphics.library',0
  986. intn:    dc.b    'intuition.library',0
  987. wbn:    dc.b    'Workbench',0
  988. audn:    dc.b    'audio.device',0
  989.  
  990.  
  991. t:    macro
  992.     ;\1    X coord (+12 will be added)
  993.     ;\2    Y coord (+12 will be added)
  994.     ;\3    string
  995.     ;\4    0 / -1 (end, continue)
  996.  
  997.     dc.b    [\1+12]/$100,[\1+12]&$FF,\2+12,\3,0,\4
  998.     endm
  999.  
  1000. audio_alert:
  1001.  t 9*8+4,0,'BACKSTAB LIBRARY ALERT: Unable to allocate audio channels.',-1
  1002.  t 9*8+4+1,0,'BACKSTAB LIBRARY ALERT: Unable to allocate audio channels.',-1
  1003.  t 25*8+4,10,'Take over channels anyway?',-1
  1004.  t 10*8,30,'Left mousebutton',-1
  1005.  t 50*8,30,'Right mousebutton',-1
  1006.  t 16*8+4,40,'YES',-1
  1007.  t 57*8+4,40,'NO',0
  1008.  
  1009. cache_alert:
  1010.  t 14*8,0,'BACKSTAB LIBRARY ALERT: Unable to disable caches',-1
  1011.  t 15*8+1,0,'BACKSTAB LIBRARY ALERT: Unable to disable caches.',-1
  1012.  t 33*8,10,'Run anyway?',-1
  1013.  t 10*8,30,'Left mousebutton',-1
  1014.  t 50*8,30,'Right mousebutton',-1
  1015.  t 16*8+4,40,'YES',-1
  1016.  t 57*8+4,40,'NO',0
  1017.  
  1018. ;77 chars / line, top left = (12,12)
  1019. ;
  1020. ;01234567890123456789012345678901234567890123456789012345678901234567890123456
  1021. ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1022. ;+1/2     BACKSTAB LIBRARY ALERT: Unable to allocate audio channels.
  1023. ;+1/2                     Take over channels anyway?
  1024. ;
  1025. ;          Left mousebutton                        Right mousebutton
  1026. ;
  1027. ;+1/2            YES                             +1/2     NO
  1028.  
  1029. ;01234567890123456789012345678901234567890123456789012345678901234567890123456
  1030. ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1031. ;             BACKSTAB LIBRARY ALERT: Unable to disable caches.
  1032. ;                                 Run anyway?
  1033. ;
  1034. ;          Left mousebutton                        Right mousebutton
  1035. ;
  1036. ;+1/2            YES                             +1/2     NO
  1037.  
  1038.  
  1039. LibName: dc.b    'backstab.library',0
  1040. LibID:     dc.b    'backstab.library 1.0',13,10,0
  1041.  
  1042.     even
  1043.  
  1044. EndOfLib:    ;LIBRARY ENDS HERE!!!
  1045.